home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byte0687.arc / TIMESET.ASM < prev   
Encoding:
Assembly Source File  |  1986-11-20  |  13.1 KB  |  425 lines

  1. ******************
  2. *                *
  3. *  TIMESET.ASM   *  Set TIME from clock cartridge
  4. *                *  <=> PUBLIC DOMAIN 09-SEP-86 <=>
  5. ******************
  6. *
  7. *** created:  07-JUN-86  by  Tim Hunkler / Solar Powered Software
  8. *
  9. * --- symbol definitions
  10. *
  11. ROM3    equ    $fa0000        ; address to strobe rom3 pin
  12. ROM4    equ    $fb0000        ; address used to strobe rom4 pin
  13. READ    equ    0        ; offset for RTC chip reads
  14. WRT    equ    64        ; offset for RTC chip writes
  15. CR    equ    $0d        ; carriage return
  16. LF    equ    $0a        ; line feed
  17. BELL    equ    $07        ; sound the bell
  18.  
  19. * ===============================
  20. * ----- PROGRAM ENTRY POINT -----
  21. * ===============================
  22. *
  23. x:    lea     x-16(pc),sp    ; set up a very small stack (240 bytes)
  24. *
  25. * --- initialize the clock cartridge after power up
  26. *
  27.     moveq     #%0001,d0    ; load control bits
  28.     moveq     #0,d1          ; addr 0 = control register                       
  29.     bsr     w_clock        ; enable clock, disable interrupts
  30. *
  31. * --- read the time from the cartridge
  32. *
  33.     movea.l     sp,a5        ; point a5 to temp buffer
  34.     bsr     r_clock    ; retrieve the time
  35.     move.w     d0,-(sp)    ; save error flag
  36. *
  37. * --- set the system time
  38. *
  39.     bsr.s     set_tos    ; set the time if no error
  40. *
  41. * --- format and display the time
  42. *
  43.     bsr     tod_fmt    ; format time for display
  44.     lea     title(pc),a0    ; point to title string
  45.  
  46.     tst.w     (sp)+        ; error reading cartridge ?
  47.     bge.s     okfine        ; no, skip
  48.     lea     errmsg(pc),a0    ; yes, change message
  49.  
  50. okfine:    bsr.s     string        ; display the string
  51. *
  52. * --- delay a bit before exiting
  53. *
  54.     move.l     #400000,d0    ; load delay count
  55. delay:    subq.l     #1,d0        ; loop till count reaches zero
  56.     bne.s     delay
  57. *
  58. * --- time to exit
  59. *
  60.     clr.w     -(sp)        ; pass function code = 0
  61.     trap     #1        ; call the system (never return)
  62.     page
  63. * ======================================
  64. * ===== string :  display a string =====
  65. * ======================================
  66. *
  67. *    in:  A0.L = string address
  68. *      out:  none
  69. *  changed:  many
  70. *
  71. *  This subroutine displays the null terminated string whose address is
  72. *  passed in A0 at the current cursor location on the screen.
  73. *
  74. string:    move.l     a0,-(sp)    ; pass string address on stack
  75.     move.w   #9,-(sp)    ; function 9 = text output
  76.     trap     #1        ; system call
  77.     addq.l   #6,sp        ; fix stack
  78.     rts
  79.  
  80. * ========================================================
  81. * ===== fetch2 : convert next two digits to a number =====
  82. * ========================================================
  83. *
  84. *    in:  A0.L = address of digits
  85. *      out:  D0.L = value of conversion
  86. *         A0.L = updated by 2
  87. *            cc's : set by D0
  88. *  changed:  D1
  89. *
  90. *  This subroutine converts the two ASCII digits pointed to by the
  91. *  address in A0 into a binary value.
  92. *
  93. fetch2:    moveq    #%1111,d0    ; load mask
  94.     and.b    (a0)+,d0    ; get 10's digit
  95.     moveq    #%1111,d1    ; load mask
  96.     and.b    (a0)+,d1    ; get 1's digit
  97.     mulu    #10,d0        ; x 10
  98.     add.w    d1,d0        ; result = d0 x 10 + d1
  99.     rts
  100.  
  101. * ====================================================
  102. * ===== set_tos :  Set the time and date for TOS =====
  103. * ====================================================
  104. *
  105. *    in:  A5.L = address of buffer returned by r_clock
  106. *         D0.W = negative value if default time desired
  107. *      out:  D7.L = date/time encoded like TOS likes it
  108. *
  109. *  changed:  A0,A1,A2,D1,D2
  110. *
  111. *  This subroutine uses the data retrieved from the clock cartridge and
  112. *  stored in a formatted buffer and converts this information into a
  113. *  format suitable for setting the time of both TOS and GEM.  System
  114. *  calls are then performed for changing the time and date.
  115. *
  116. set_tos:
  117.     move.l     #$0C215000,d7    ; preload   01/01/86 10:00:00
  118.     tst.w     d0        ; do we want default or real time?
  119.     bmi.s     stdef        ; branch for default 
  120. *
  121. * --- format the date:  [yyyyyyy mmmm ddddd]
  122. *
  123.     lea     2(a5),a0    ; point to first year digit
  124.     bsr.s     fetch2        ; get year (00= 1980)
  125.     move.l     d0,d7        ; place year into d7
  126.  
  127.     bsr.s     fetch2        ; get month, 1..12
  128.     lsl.w     #4,d7        ; form:  ????? yyyyyyy 0000
  129.     or.w     d0,d7        ; add in the month
  130.  
  131.     bsr.s     fetch2        ; get day of month, 1..31
  132.     lsl.w     #5,d7        ; form:  yyyyyyy mmmm 00000
  133.     or.w     d0,d7        ; add in the day
  134. *
  135. * --- encode the time:    [hhhhh mmmmmm sssss]
  136. *
  137.     swap     d7        ; put year/month/day in upper word
  138.  
  139.     bsr.s     fetch2        ; get hour, 0..23
  140.     move.w     d0,d7        ; form in low word:  ??????????? hhhhh
  141.  
  142.     bsr.s     fetch2        ; get minute, 0..59
  143.     lsl.w     #6,d7        ; form:  ????? hhhhh 000000
  144.     or.w     d0,d7        ; add in the minutes
  145.  
  146.     bsr.s     fetch2        ; get seconds, 0..59
  147.     lsl.w     #5,d7        ; form:  hhhhh mmmmmm 00000
  148.     lsr.w     #1,d0        ; divide seconds by 2
  149.     addx.w     d0,d7        ; add in seconds (with rounding)
  150. *
  151. * --- set the TOS time    [date : time ]
  152. *
  153. stdef:    move.w     d7,-(sp)    ; pass the new time
  154.     move.w     #45,-(sp)    ; pass function code = set time
  155.     trap     #1        ; call system
  156.     addq.l     #4,sp        ; fix stack
  157. *
  158. * --- set the GEM date and time:   [ date : time ]
  159. *    
  160.     move.l     d7,-(sp)    ; pass the date and time
  161.     move.w     #22,-(sp)    ; pass function code = set date and time
  162.     trap     #14        ; call system
  163.     addq.l     #6,sp        ; fix stack
  164. *
  165. * --- set the TOS date
  166. *
  167.     swap     d7        ; retrieve date to low word
  168.     move.w     d7,-(sp)    ; pass the date
  169.     move.w     #43,-(sp)    ; pass function code = set date
  170.     trap     #1        ; call system
  171.     addq.l     #4,sp        ; fix stack
  172.     rts
  173.  
  174. * =====================================
  175. * ===== w_clock :  write to clock =====
  176. * =====================================
  177. *
  178. *    in:  D0.B = data to be written
  179. *            D1.W = register address x 2 to be written to
  180. *
  181. *      out:  A3.L = pointer to clock address latch
  182. *            A4.L = pointer to clock chip select
  183. *         D1.W = increased by 2
  184. *            D0.W = data present prior to write
  185. *            cc's : set by D0
  186. *
  187. *  changed:  A0,D2
  188. *
  189. *  This subroutine is used to write data to the clock chip.  The data
  190. *  to be written is passed in the lower 4 bits of D0 and 2 times the
  191. *  clock register to be accessed in passed in D1.
  192. *
  193. w_clock:
  194.     lea    ROM3,a3        ; LATCH address
  195.     lea    ROM4,a4        ; CS low strobe
  196. *
  197. * --- form the clock register address
  198. *
  199. wcep:    lea    0(a3,d1.w),a0    ; form proper address
  200. *
  201. * --- mask off 4 bit data and align it into address bits 12..15
  202. *
  203.     moveq    #15,d2        ; load mask
  204.     and.w    d0,d2        ; mask of 4 bit data item
  205.     ror.w    #4,d2        ; rotate to upper bits
  206. *
  207. * --- latch address, data, and enable writes to the chip
  208. *
  209.     move.b    WRT(a0,d2.l),d0    ; read old data, latch new data
  210. *
  211. * --- turn chip select on to start the write operation
  212. *
  213.     tst.w    (a4)        ; set chip select low
  214.     addq.w    #2,d1        ; update register address
  215. *
  216. * --- turn off write enable, turn off chip select, but hold data
  217. *
  218.     tst.b    READ(a0,d2.l)    ; set chip select high
  219.     andi.w    #$000F,d0    ; mask off 4 bit data and set cond codes
  220.     rts
  221.  
  222. * =====================================
  223. * ===== r_clock : read from clock =====
  224. * =====================================
  225. *
  226. *    in:  A3.L = pointer to clock latch address
  227. *            A4.L = pointer to chip select strobe address
  228. *            A5.L = address of 16 byte buffer to be filled
  229. *
  230. *      out:  D0.L = 0 if all OK, else -1
  231. *            cc's : set by D0
  232. *            (A5) ---> [ flag bits   ]    leap count, AM/PM, 12/24 hour
  233. *                 +1   [ day of week ]  1=Sunday
  234. *                 +2   [ year x 10   ]    00 = 1980, 01 = 1981, etc.
  235. *                 +3   [ year x 1    ]
  236. *                 +4   [ month x 10  ]
  237. *                 +5   [ month x 1   ]
  238. *                      [ day x 10    ]
  239. *                      [ day x 1     ]
  240. *                      [ hour x 10   ]
  241. *                      [ hour x 1    ]
  242. *                      [ minute x 10 ]
  243. *                      [ minute x 1  ]
  244. *                      [ second x 10 ]
  245. *                      [ second x 1  ]
  246. *                 +14  [ .1 seconds  ]
  247. *                 +15  [ junk byte   ]
  248. *
  249. *  changed:  A0,D1,D2
  250. *
  251. *  This subroutine reads all time and date registers from the clock chip
  252. *  and fills a 16 byte buffer whose address was passed in A5.  As the
  253. *  information is read it is added up.  Invalid sums typically indicate
  254. *  a dead battery or a clock cartridge which is not present and are
  255. *  indicated by returning a -1 in register D0 and the condition codes.
  256. *  A data changed bit is check and if the time changed while the read
  257. *  operation was in progress the operation is repeated.
  258. *
  259. r_clock:
  260.     movea.l     a3,a0        ; set pntr to register 0
  261.     lea     16(a5),a5    ; point to end of buffer to fill
  262.     moveq     #0,d1        ; set accumulator to zero
  263. *
  264. * --- preload the register address in the latch
  265. *
  266.     tst.w     (a0)+        ; set register selection to 0
  267. *
  268. * --- loop and read clock registers 0..15
  269. *
  270.     moveq     #15,d2        ; loop count = 16
  271. fetch:    tst.w     (a4)        ; set chip select on
  272.     moveq     #15,d0        ; load 4 bit data mask
  273.     and.w     (a0)+,d0    ; get data, set next addr, select off
  274.     move.b     d0,-(a5)    ; store data in buffer
  275.     add.w     d0,d1        ; add up all data values
  276.     dbf     d2,fetch    ; and repeat for 16 items
  277. *
  278. * --- retrieve data changed flag (zero indicates no change occurred)
  279. *
  280.     tst.w     (a4)        ; set CS low with register select = 0
  281.     moveq     #8,d0        ; load mask
  282.     and.w     (a0),d0    ; get flag, nxt addr = 2, select = off
  283. *
  284. * --- if no clock present we generally accumulate 16x15 = 240
  285. *
  286.     cmpi.w     #125,d1    ; does accumulate indicate bad data?
  287.     ble.s     nwflg        ; no, branch
  288.     moveq     #-1,d0        ; yes, set error flag
  289. *
  290. * --- test data changed flag and reread the time if necessary
  291. *
  292. nwflg:    tst.w     d0        ; was data changed (or an error)?
  293.     bgt.s     r_clock    ; yes, then repeat the time reading
  294.     rts            ; no, exit with cond codes set
  295.  
  296. * =========================================================
  297. * ===== xlate : Translate two bytes into ASCII digits =====
  298. * =========================================================
  299. *
  300. *    in:  A0.L = address of two bytes in the range 0..9
  301. *         A1.L = destination address for ASCII digits
  302. *      out:  A0.L = incremented by 2
  303. *            A1.L = incremented by 3
  304. *  changed:  none
  305. *
  306. *  This subroutine converts two bytes addressed by A1 into ASCII digits
  307. *  in the range '0..9' and increments the address pointer by 3.
  308. *
  309. xlate:    bsr.s     dt        ; convert digit one
  310.     bsr.s     dt        ; convert digit two
  311.     addq.l     #1,a1        ; skip ahead one place
  312.     rts
  313.  
  314. dt:    move.b     (a0)+,(a1)    ; copy byte
  315.     addi.b     #$30,(a1)+    ; convert copied byte to ASCII
  316.     rts
  317.  
  318. * ===========================================
  319. * ===== B2D :  Binary to Decimal String =====
  320. * ===========================================
  321. *
  322. *    in:  D0.W = value to convert, range = 0..99
  323. *         A1.L = destination buffer
  324. *      out:  A1.L = incremented by 2
  325. *  changed:  D0
  326. *
  327. *  This subroutine converts the value passed in D0.W which should be in
  328. *  the range of 0..99 into a two digit ASCII string and stores these
  329. *  digits at the address passed in A1.
  330. *
  331. b2d:    ext.l    d0        ; extend word into longword
  332.     divu    #10,d0        ; divide to separte ten's and one's
  333.     addi.b    #$30,d0        ; convert ten's digit to ASCII
  334.     move.b     d0,(a1)+    ; store ten's digit
  335.     swap     d0        ; swap remainder to low word
  336.     addi.b     #$30,d0    ; convert one's digit to ASCII
  337.     move.b     d0,(a1)+    ; store one's digit
  338.     rts
  339.  
  340. * ==================================================
  341. * ===== tod_fmt :  format time of day and date =====
  342. * ==================================================
  343. *
  344. *    in:  A5.L = pointer to retrieved time buffer
  345. *      out:  none
  346. *  changed:  A0,A1,D0,D1,?
  347. *
  348. *  This subroutine takes the data block returned by the subroutine
  349. *  'r_clock' and formats it into a string of the form:
  350. *
  351. *      "WED  07-SEP-86  12:42 AM"
  352. *
  353. tod_fmt:
  354.     lea    time+3(pc),a1    ; address day of week field
  355.     lea     1(a5),a0    ; pnt to day of week byte
  356.     
  357.     moveq     #0,d0        ; ensure we start with zero
  358.     move.b     (a0)+,d0    ; get day of week, 1..7
  359.     lsl.w     #2,d0        ; form 4x which is byte offset
  360.     move.l     t_day-4(pc,d0.w),(a1)+    ; install string like "MON "
  361.  
  362.     addq.l     #8,a1        ; address year field
  363.     bsr     fetch2        ; fetch the year, 0..99
  364.     addi.w     #80,d0        ; convert 0 into 80
  365.     bsr.s     b2d        ; format as decimal string
  366.  
  367.     lea     time+11(pc),a1    ; address month field
  368.     bsr     fetch2        ; fetch the month, 1..12
  369.     lsl.w     #2,d0        ; form 4x which is byte offset
  370.     move.l     month-4(pc,d0.w),(a1) ; install string like "JAN-"
  371.  
  372.     subq.l     #3,a1        ; address day of month 
  373.     bsr.s     xlate        ; copy and translate day of the month
  374.  
  375.     addq.l     #8,a1        ; address hours field
  376.     bsr     fetch2        ; fetch hours, 0..23
  377.     moveq     #$41,d2    ; preload "A" for AM
  378.     tst.w     d0        ; is time 00:xx ?
  379.     bne.s     ampm        ; no, skip 
  380.     moveq     #12,d0        ; yes, change 00:xx into 12:xx
  381.     bra.s     AM
  382.  
  383. ampm:    cmpi.w     #12,d0        ; are we after noon?
  384.     blt.s     AM        ; no, skip
  385.     beq.s     NOON        ; if before 1:00pm just update character
  386.     subi.w     #12,d0        ; convert 13:00 into 1:00
  387. NOON:    moveq     #$50,d2    ; change character to "P"
  388.  
  389. AM:    bsr.s     b2d        ; format hours as decimal string
  390.     addq.l     #1,a1        ; advance over colon
  391.     bsr.s     xlate        ; minutes
  392.     bsr.s     xlate        ; seconds
  393.  
  394.     move.b     d2,(a1)    ; install AM or PM
  395.     rts
  396. *    
  397. * --- This is a table for converting 1..7 into a day of week string
  398. *
  399. t_day:    dc.l    'Sun ','Mon ','Tue ','Wed '
  400.     dc.l    'Thu ','Fri ','Sat '
  401. *
  402. * --- This is a table for converting 1..12 into a month string
  403. *
  404. month:    dc.l    'Jan-','Feb-','Mar-','Apr-'
  405.     dc.l    'May-','Jun-','Jul-','Aug-'
  406.     dc.l    'Sep-','Oct-','Nov-','Dec-'
  407. *
  408. * --- the title and time and date display
  409. *
  410. title:    dc.b    CR,LF,LF
  411.     dc.b    '=TIMESET v1.0='
  412. time:    dc.b    CR,LF
  413.     dc.b    ' WED  xx-xxx-xx  xx:xx:xx xM'
  414.     dc.b    CR,LF,0
  415. *
  416. * --- error message
  417. *
  418. errmsg:    dc.b    CR,LF,BELL
  419.     dc.b    '=TIMESET='
  420.     dc.b    CR,LF
  421.     dc.b    ' * Check Clock Battery!'
  422.     dc.b    CR,LF,0
  423.  
  424.     end
  425.